package com.aegean.socket.base;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Set;
import java.util.logging.Logger;

import com.aegean.tool.MyTools;

public class TradionalSocketTCPNIOServer extends Thread {
	private SocketChannel sc = null;
	private ServerSocketChannel ssc = null;
	private ServerSocket ss = null;
	private Selector selector = null;
	private SelectionKey skey = null;
	private Handler handler = new serviceHandler();
	private CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
	private CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
	private  String writeMsg = null;
	private static final Logger log = Logger
			.getLogger(TradionalSocketTCPNIOClient.class.getName());
	private final int pocketAddress = 8888;
	private final InetSocketAddress inetAD = new InetSocketAddress(
			pocketAddress);

	public static void main(String[] args) throws Exception {
		new TradionalSocketTCPNIOServer().run();

	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		if (init() == true) {
			//for(int i=0;i<10;i++) 
			while(true){
				operation();
			}
		} else {
			System.out.println("The initialization of server is false!");
		}

	}

	private boolean init() {
		try {
			ssc = ServerSocketChannel.open();
			ss = ssc.socket();
			ss.bind(inetAD);
			ssc.configureBlocking(false);// 不进行赌赛
			selector = Selector.open();
			ssc.register(selector, SelectionKey.OP_ACCEPT);// 准备连接服务器就绪
			return true;
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return false;
		}
	}

	private boolean operation() {
		try {
			int nkeys = selector.select();
			System.out.println("The total count of server Optimate Selector:"
					+ nkeys);
			if (nkeys > 0) {
				Set<SelectionKey> keys = selector.selectedKeys();// 获取被注册的channel
				for (SelectionKey key : keys) {
					if (key.isConnectable()) {
						System.out.println("Server connection is open");
					} else if (key.isReadable()) {
						System.out.println("Server reader is open");
						handler.NIOReader(key);
					} else if (key.isWritable()) {
						System.out.println("Server writter is open");
						handler.NIOWritter(key);
					} else if (key.isAcceptable()) {
						System.out.println("Server acception is open");
						handler.NIOAcception(key);
					}
				}
				selector.selectedKeys().clear();
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return false;
		}
		return true;
	}

	interface Handler {
		void NIOReader(SelectionKey key);

		void NIOWritter(SelectionKey key);

		void NIOAcception(SelectionKey key);
	}

	class serviceHandler implements Handler {

		@Override
		public void NIOReader(SelectionKey key) {
			// TODO Auto-generated method stub
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			SocketChannel channel = (SocketChannel) key.channel();
			try {
				System.out.println("收到客户端消息："
						+ channel.socket().getInetAddress().getHostName()
						+ channel.socket().getInetAddress().getHostAddress()
						+ ":");
				while (true) {
					int readBytes = channel.read(buffer);
					if (readBytes > 0) {
						log.info("Server: readBytes = " + readBytes);
					    	System.out.println("Server: data = "
									+ MyTools.toChinese(new String(buffer.array(),0,readBytes)));
						buffer.flip();
					} else
						break;
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (buffer != null)
					buffer.clear();
				try {
					String msg="Server had accepted the message from client!";
					channel.register(selector, SelectionKey.OP_WRITE,msg);
					channel.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}

		@Override
		public void NIOWritter(SelectionKey key) {
			System.out.println("server niowritter!!!!!!!!!");
			// TODO Auto-generated method stub
			//key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
			writeMsg=key.attachment().toString();
			SocketChannel channel = (SocketChannel) key.channel();
			int writtedSize = 0;
			if (writeMsg == null || writeMsg.equals("")) {
				log.info("writed message is empty!");
			} else {
				try {
					writtedSize = channel.write(ByteBuffer.wrap(writeMsg.getBytes()));
					if (writtedSize == 0) {
						channel.register(selector, SelectionKey.OP_WRITE);
					}
				} catch (Exception e) {
					// TODO: handle exception
					log.info("The sending message is countering the error!");
					e.printStackTrace();
				}
			}
			try {
				sc.register(selector,SelectionKey.OP_READ);
			} catch (ClosedChannelException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		@Override
		public void NIOAcception(SelectionKey key) {
			// TODO Auto-generated method stub
			SocketChannel sc = null;
			try {
				ServerSocketChannel server = (ServerSocketChannel) key
						.channel();
				sc = server.accept();
				sc.configureBlocking(false);
				System.out.println("收到客户端连接："
						+ sc.socket().getInetAddress().getHostName()
						+ sc.socket().getInetAddress().getHostAddress());
				sc.register(selector, SelectionKey.OP_READ);				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}
